/**
 * 每日练习服务层
 */
const dailyDao = require('../dao/dailyDao');
const userDao = require('../dao/userDao');
const { validatePagination } = require('../utils/validation');

/**
 * 获取每日练习内容服务
 * @param {number} userId - 用户ID
 * @param {string} date - 日期 (YYYY-MM-DD)
 * @returns {Object} 每日练习内容
 */
const getDailyPractice = async (userId, date = null) => {
  const targetDate = date || new Date().toISOString().split('T')[0];
  
  // 获取每日练习内容
  const dailyContent = await dailyDao.getDailyPracticeByDate(targetDate);
  if (!dailyContent) {
    throw new Error('今日暂无练习内容');
  }

  // 检查用户是否已完成今日练习
  let userProgress = null;
  let isCompleted = false;
  
  if (userId) {
    userProgress = await dailyDao.getUserDailyProgress(userId, targetDate);
    isCompleted = userProgress ? userProgress.is_completed : false;
  }

  return {
    id: dailyContent.id,
    date: dailyContent.date,
    title: dailyContent.title,
    description: dailyContent.description,
    content: dailyContent.content,
    type: dailyContent.type,
    difficulty: dailyContent.difficulty,
    estimatedTime: dailyContent.estimated_time,
    points: dailyContent.points,
    isCompleted,
    progress: userProgress ? {
      score: userProgress.score,
      completedAt: userProgress.completed_at,
      timeSpent: userProgress.time_spent
    } : null
  };
};

/**
 * 提交每日练习结果服务
 * @param {number} userId - 用户ID
 * @param {number} practiceId - 练习ID
 * @param {Object} resultData - 练习结果数据
 * @returns {Object} 提交结果
 */
const submitDailyPractice = async (userId, practiceId, resultData) => {
  const { score, answers, timeSpent } = resultData;

  // 检查练习是否存在
  const practice = await dailyDao.getDailyPracticeById(practiceId);
  if (!practice) {
    throw new Error('练习不存在');
  }

  // 检查是否已完成
  const existingProgress = await dailyDao.getUserDailyProgress(userId, practice.date);
  if (existingProgress && existingProgress.is_completed) {
    throw new Error('今日练习已完成');
  }

  // 创建或更新练习记录
  const progressData = {
    user_id: userId,
    practice_id: practiceId,
    date: practice.date,
    score: score,
    answers: answers,
    time_spent: timeSpent,
    is_completed: true,
    completed_at: new Date()
  };

  let progress;
  if (existingProgress) {
    progress = await dailyDao.updateUserDailyProgress(userId, practice.date, progressData);
  } else {
    progress = await dailyDao.createUserDailyProgress(progressData);
  }

  // 更新用户连续签到天数
  await updateUserStreak(userId, practice.date);

  // 增加用户经验值
  await addUserExperience(userId, practice.points);

  return {
    score: score,
    points: practice.points,
    timeSpent: timeSpent,
    streak: await getUserStreak(userId),
    totalPoints: await getUserTotalPoints(userId)
  };
};

/**
 * 获取用户练习历史服务
 * @param {number} userId - 用户ID
 * @param {Object} query - 查询参数
 * @returns {Object} 练习历史分页结果
 */
const getUserPracticeHistory = async (userId, query) => {
  const { page, limit } = validatePagination(query);
  const { startDate, endDate, type } = query;

  const options = {
    user_id: userId,
    start_date: startDate,
    end_date: endDate,
    type,
    page,
    limit
  };

  const result = await dailyDao.getUserPracticeHistory(options);

  const formattedList = result.practices.map(practice => ({
    id: practice.id,
    date: practice.date,
    title: practice.daily_practice ? practice.daily_practice.title : '',
    type: practice.daily_practice ? practice.daily_practice.type : '',
    difficulty: practice.daily_practice ? practice.daily_practice.difficulty : '',
    score: practice.score,
    points: practice.daily_practice ? practice.daily_practice.points : 0,
    timeSpent: practice.time_spent,
    completedAt: practice.completed_at
  }));

  return {
    list: formattedList,
    total: result.total,
    page,
    limit
  };
};

/**
 * 获取用户练习统计服务
 * @param {number} userId - 用户ID
 * @returns {Object} 练习统计数据
 */
const getUserPracticeStats = async (userId) => {
  const stats = await dailyDao.getUserPracticeStatistics(userId);
  const streak = await getUserStreak(userId);
  const totalPoints = await getUserTotalPoints(userId);

  return {
    totalPractices: stats.total_practices || 0,
    completedPractices: stats.completed_practices || 0,
    averageScore: parseFloat(stats.average_score || 0),
    totalTimeSpent: stats.total_time_spent || 0,
    currentStreak: streak,
    longestStreak: stats.longest_streak || 0,
    totalPoints: totalPoints,
    thisMonthPractices: stats.this_month_practices || 0
  };
};

/**
 * 获取练习日历服务
 * @param {number} userId - 用户ID
 * @param {string} year - 年份
 * @param {string} month - 月份
 * @returns {Object} 练习日历数据
 */
const getPracticeCalendar = async (userId, year, month) => {
  const startDate = `${year}-${month.padStart(2, '0')}-01`;
  const endDate = new Date(year, month, 0).toISOString().split('T')[0]; // 月末日期

  const practices = await dailyDao.getUserPracticesByDateRange(userId, startDate, endDate);

  const calendar = {};
  practices.forEach(practice => {
    calendar[practice.date] = {
      completed: practice.is_completed,
      score: practice.score,
      points: practice.daily_practice ? practice.daily_practice.points : 0
    };
  });

  return {
    year: parseInt(year),
    month: parseInt(month),
    calendar
  };
};

/**
 * 获取排行榜服务
 * @param {Object} query - 查询参数
 * @returns {Object} 排行榜数据
 */
const getPracticeLeaderboard = async (query) => {
  const { type = 'points', period = 'month', page, limit } = query;
  const { page: validPage, limit: validLimit } = validatePagination({ page, limit });

  const result = await dailyDao.getPracticeLeaderboard({
    type,
    period,
    page: validPage,
    limit: validLimit
  });

  const formattedList = result.rankings.map((ranking, index) => ({
    rank: (validPage - 1) * validLimit + index + 1,
    userId: ranking.user_id,
    username: ranking.user ? ranking.user.username : '',
    nickname: ranking.user ? ranking.user.nickname : '',
    avatar: ranking.user ? ranking.user.avatar : '',
    points: ranking.total_points || 0,
    practiceCount: ranking.practice_count || 0,
    averageScore: parseFloat(ranking.average_score || 0),
    streak: ranking.current_streak || 0
  }));

  return {
    list: formattedList,
    total: result.total,
    page: validPage,
    limit: validLimit
  };
};

/**
 * 更新用户连续签到天数（辅助函数）
 * @param {number} userId - 用户ID
 * @param {string} date - 日期
 */
const updateUserStreak = async (userId, date) => {
  const user = await userDao.findById(userId);
  if (!user) return;

  const today = new Date(date);
  const yesterday = new Date(today);
  yesterday.setDate(yesterday.getDate() - 1);

  // 检查昨天是否有练习记录
  const yesterdayProgress = await dailyDao.getUserDailyProgress(userId, yesterday.toISOString().split('T')[0]);
  
  let newStreak = 1;
  if (yesterdayProgress && yesterdayProgress.is_completed) {
    newStreak = (user.streak || 0) + 1;
  }

  await userDao.updateUser(userId, { streak: newStreak });
};

/**
 * 增加用户经验值（辅助函数）
 * @param {number} userId - 用户ID
 * @param {number} points - 经验值
 */
const addUserExperience = async (userId, points) => {
  const user = await userDao.findById(userId);
  if (!user) return;

  const newExperience = (user.experience || 0) + points;
  await userDao.updateUser(userId, { experience: newExperience });
};

/**
 * 获取用户连续签到天数（辅助函数）
 * @param {number} userId - 用户ID
 * @returns {number} 连续签到天数
 */
const getUserStreak = async (userId) => {
  const user = await userDao.findById(userId);
  return user ? (user.streak || 0) : 0;
};

/**
 * 获取用户总积分（辅助函数）
 * @param {number} userId - 用户ID
 * @returns {number} 总积分
 */
const getUserTotalPoints = async (userId) => {
  const stats = await dailyDao.getUserTotalPoints(userId);
  return stats.total_points || 0;
};

module.exports = {
  getDailyPractice,
  submitDailyPractice,
  getUserPracticeHistory,
  getUserPracticeStats,
  getPracticeCalendar,
  getPracticeLeaderboard
};
